package controllers

import (
	"fmt"
	"github.com/gin-gonic/gin"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"github.com/rifflock/lfshook"
	"github.com/sirupsen/logrus"
	"net/http"
	"os"
	"path"
	"time"
)

var log = logrus.New() // 创建一个log示例
func initLogrus() error {
	log.Formatter = &logrus.JSONFormatter{} // 设置为json格式的日志

	//os.O_CREATE: 如果文件不存在则创建
	//os.O_WRONLY: 以读写的方式打开
	//os.O_APPEND: 追加写入
	//0644: 文件权限
	file, err := os.OpenFile("./logs/http_api.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) // 创建一个log日志文件
	if err != nil {
		fmt.Println("文件打开或创建失败")
		return err
	}
	log.Out = file               // 设置log的默认文件输出
	gin.SetMode(gin.ReleaseMode) // 发布版本
	gin.DefaultWriter = log.Out  // 如果设置此项，gin框架自己记录的日志也会写入到文件
	log.Level = logrus.InfoLevel // 设置日志级别
	return nil
}

// 使用logrus写入日志文件
// 文档地址：https://github.com/sirupsen/logrus
func LogrusDemo1(c *gin.Context) {
	err := initLogrus()
	if err != nil {
		fmt.Println(err)
		return
	}

	//log日志信息的写入
	log.WithFields(logrus.Fields{
		"url":    c.Request.RequestURI, //自定义显示的字段，下同
		"method": c.Request.Method,
		"params": c.Query("name"),
		"IP":     c.ClientIP(),
	}).Info()
	resData := struct {
		Code int         `json:"code"`
		Msg  string      `json:"msg"`
		Data interface{} `json:"data"`
	}{http.StatusOK, "响应成功", "OK"}
	c.JSON(http.StatusOK, resData)
}

// 日志文件自动切割以及过期删除
// file-rotatelogs: https://github.com/lestrrat-go/file-rotatelogs
// lfshook: https://github.com/rifflock/lfshook
func LogMiddleware() gin.HandlerFunc {
	var (
		logFilePath = "./logs" //文件存储路径
		logFileName = "system.log"
	)
	// 日志文件
	fileName := path.Join(logFilePath, logFileName)
	// 写入文件
	file, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		fmt.Println(err)
	}
	// 实例化
	logger := logrus.New()
	//设置日志级别
	logger.SetLevel(logrus.DebugLevel)
	//设置输出
	logger.Out = file
	// 设置 rotatelogs,实现文件分割
	logWriter, err := rotatelogs.New(
		// 分割后的文件名称
		fileName+".%Y%m%d.log",
		// 生成软链，指向最新日志文件
		rotatelogs.WithLinkName(fileName),
		// 设置最大保存时间(7天)
		rotatelogs.WithMaxAge(7*24*time.Hour), //以hour为单位的整数
		// 设置日志切割时间间隔(1天)
		rotatelogs.WithRotationTime(1*time.Hour),
	)
	//hook机制的设置
	writerMap := lfshook.WriterMap{
		logrus.InfoLevel:  logWriter,
		logrus.FatalLevel: logWriter,
		logrus.DebugLevel: logWriter,
		logrus.WarnLevel:  logWriter,
		logrus.ErrorLevel: logWriter,
		logrus.PanicLevel: logWriter,
	}
	//给logrus添加hook
	logger.AddHook(lfshook.NewHook(writerMap, &logrus.JSONFormatter{
		TimestampFormat: "2006-01-02 15:04:05",
	}))
	return func(c *gin.Context) {
		c.Next()
		//请求方式
		method := c.Request.Method
		//请求路由
		reqUrl := c.Request.RequestURI
		//状态码
		statusCode := c.Writer.Status()
		//请求ip
		clientIP := c.ClientIP()
		logger.WithFields(logrus.Fields{
			"status_code": statusCode,
			"client_ip":   clientIP,
			"req_method":  method,
			"req_uri":     reqUrl,
		}).Info()
	}

}
func LogrusDemo2(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "响应成功",
		"data": "OK",
	})
}
